package zilvic.resources.sprites;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import org.duncan.Math2D.Point2D;

/**
 * A sprite to be displayed on the screen. Note that a sprite
 * contains no state information, i.e. its just the image and
 * not the location. This allows us to use a single sprite in
 * lots of different places without having to store multiple
 * copies of the image.
 * 
 * @author Kevin Glass
 */
public class Sprite implements Drawable {
    /** The image to be drawn for this sprite */
    private Image image;
    private String name;

    /**
     * Create a new sprite based on an image
     *
     * @param image The image that is this sprite
     */
    public Sprite(Image image, String name) {
        this.image = image;
        this.name  = name;
    }

    /**
     * Get the width of the drawn sprite
     *
     * @return The width in pixels of this sprite
     */
    public int getWidth() {
        return image.getWidth(null);
    }

    /**
     * Get the height of the drawn sprite
     *
     * @return The height in pixels of this sprite
     */
    public int getHeight() {
        return image.getHeight(null);
    }

    /**
     * Sets the name of this string.
     * @param name The new name.
     * @return A reference to this.
     */
    public Sprite setName(String name) {
        this.name = name;
        return this;
    }

    /**
     * Returns the name of this string.
     * @return The name.
     */
    public String getName() {
        return name;
    }

    /**
     * Sets the image of this sprite.
     * @param image The new image.
     * @return A reference to this.
     */
    public Sprite setImage(Image image) {
        this.image = image;
        return this;
    }

    /**
     * Returns the image of this sprite.
     * @return The image.
     */
    public Image getImage() {
        return image;
    }

    /**
     * Splits this sprite into an sequence and returns it.
     * @return The new sequence.
     */
    public Sequence toSequence() {
        Sequence s = new Sequence();
        int tile_count = 4;
        for (int i = 0; i < tile_count; i++) {
            BufferedImage img = new BufferedImage(
                    getWidth() / tile_count,
                    getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            g.drawImage(image, 0, 0,
                    getWidth() / tile_count, getHeight(),
                    getWidth() / tile_count * i,
                    0, getWidth() / tile_count,
                    getHeight(), null);
            s.add(new Sprite(img, ""));
        }
       return s;
    }

    /**
     * Splits this sprite into an ActorSprite and returns it.
     * @return The new sequence.
     */
    public ActorSprite toActorSprite() {
        ActorSprite as = new ActorSprite();
        byte row_count = 4;
        for (byte i = 0; i < row_count; i++) {
            BufferedImage img = new BufferedImage(
                    getWidth(),
                    getHeight() / row_count,
                    BufferedImage.TYPE_INT_ARGB);
            Graphics g = img.getGraphics();
            g.drawImage(image, 0, 0,
                    getWidth(), getHeight() / row_count, 0,
                    getHeight() / row_count * i, getWidth(),
                    getHeight() / row_count, null);
            as.setSequence(i, new Sprite(img, "").toSequence());
        }
       return as;
    }

    /**
     * Draw the sprite onto the graphics context provided
     *
     * @param g The graphics context on which to draw the sprite
     * @param position The location at which to draw the sprite
     * @param step The step of the animation. Can be either 0, 1, 2, or 3. THIS
     * PARAMETER IS NOT USED IN THIS CLASS.
     * @param direction The direction of the sprite. THIS PARAMETER IS NOT USED
     * IN THIS CLASS.
     * @See Actor
     * @return A reference to this.
     */
    public Sprite draw(Graphics g, Point2D position, byte step, byte direction) {
        g.drawImage(image, 
                (int) position.getX(),
                (int) position.getY(), null);
        return this;
    }
}